package me.flyray.crm.core.biz.customer;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import me.flyray.common.enums.CustomerType;
import me.flyray.common.msg.BizResponseCode;
import me.flyray.common.util.SnowFlake;
import me.flyray.crm.facade.request.AccountTransferRequest;
import me.flyray.crm.facade.request.IntoAccountRequest;
import me.flyray.crm.facade.request.UnfreezeAndOutAccountRequest;
import me.flyray.crm.facade.request.UnfreezeAndTransferRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import me.flyray.common.enums.AccountState;
import me.flyray.common.enums.AccountTransferType;
import me.flyray.common.enums.InOutFlag;
import me.flyray.common.util.EntityUtils;
import me.flyray.common.util.MD5;
import me.flyray.crm.core.entity.MerchantAccount;
import me.flyray.crm.core.entity.MerchantAccountJournal;
import me.flyray.crm.core.entity.PersonalAccount;
import me.flyray.crm.core.entity.PersonalAccountJournal;
import me.flyray.crm.core.entity.PlatformAccoutConfig;
import me.flyray.crm.core.mapper.MerchantAccountJournalMapper;
import me.flyray.crm.core.mapper.MerchantAccountMapper;
import me.flyray.crm.core.mapper.PersonalAccountJournalMapper;
import me.flyray.crm.core.mapper.PersonalAccountMapper;
import me.flyray.crm.core.mapper.PlatformAccoutConfigMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * 转账相关的操作
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@Service
public class CustomerAccountTransferBiz {

	@Value("${crm.account.balanceSaltValue}")
	private String balanceSaltValue;
	@Autowired
	private MerchantAccountMapper merAccountMapper;
	@Autowired
	private PersonalAccountMapper personalAccountMapper;
	@Autowired
	private PersonalAccountJournalMapper personalAccountJournalMapper;
	@Autowired
	private MerchantAccountJournalMapper merchantAccountJournalMapper;
	@Autowired
	private PlatformAccoutConfigMapper platformAccoutConfigMapper;
	@Autowired
	private CustomerOutAccountBiz customerOutAccountBiz;

	/**
	 * 个人或者商户转账接口 
	 */
	public Map<String, Object> accountTransfer(AccountTransferRequest accountTransferRequest) {
		log.info("个人或者商户入账相关的接口 请求参数：{}" + EntityUtils.beanToMap(accountTransferRequest));
		Map<String, Object> response = new HashMap<String, Object>();
		//个人转个人
		if(AccountTransferType.p2p.getCode().equals(accountTransferRequest.getTransferType())){
			log.info("个人或者商户入账相关的接口-个人账户转个人账户");
			Map<String, Object>intoPerAccount=personAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getIntoAccountId(),accountTransferRequest.getIntoAccountType(),accountTransferRequest.getIntoCustomerType(), InOutFlag.in.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(intoPerAccount.get("code"))){
				return intoPerAccount;
			}
			Map<String, Object>outPerAccount=personAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getOutAccountId(),accountTransferRequest.getOutAccountType(),accountTransferRequest.getOutCustomerType(), InOutFlag.out.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(outPerAccount.get("code"))){
				return outPerAccount;
			}
		}
		//个人转商户
		if(AccountTransferType.p2m.getCode().equals(accountTransferRequest.getTransferType())){
			log.info("个人或者商户入账相关的接口-个人账户转商户账户");
			Map<String, Object>intoMerAccount=merchantAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getIntoAccountId(),accountTransferRequest.getIntoAccountType(),accountTransferRequest.getIntoCustomerType(), InOutFlag.in.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(intoMerAccount.get("code"))){
				return intoMerAccount;
			}
			Map<String, Object>outPerAccount=personAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getOutAccountId(),accountTransferRequest.getOutAccountType(),accountTransferRequest.getOutCustomerType(), InOutFlag.out.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(outPerAccount.get("code"))){
				return outPerAccount;
			}
		}
		//商户转商户
		if(AccountTransferType.m2m.getCode().equals(accountTransferRequest.getTransferType())){
			log.info("个人或者商户入账相关的接口-商户账户转商户账户");
			Map<String, Object>intoMerAccount=merchantAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getIntoAccountId(),accountTransferRequest.getIntoAccountType(),accountTransferRequest.getIntoCustomerType(), InOutFlag.in.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(intoMerAccount.get("code"))){
				return intoMerAccount;
			}
			Map<String, Object>outMerAccount=merchantAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getOutAccountId(),accountTransferRequest.getOutAccountType(),accountTransferRequest.getOutCustomerType(), InOutFlag.out.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(outMerAccount.get("code"))){
				return outMerAccount;
			}
		}
		//商户转个人
		if(AccountTransferType.m2p.getCode().equals(accountTransferRequest.getTransferType())){
			log.info("个人或者商户入账相关的接口-商户账户转个人账户");
			Map<String, Object>outPerAccount=personAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getIntoAccountId(),accountTransferRequest.getIntoAccountType(),accountTransferRequest.getIntoCustomerType(), InOutFlag.in.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(outPerAccount.get("code"))){
				return outPerAccount;
			}
			Map<String, Object>outMerAccount=merchantAccountOperate(accountTransferRequest.getPlatformId(),accountTransferRequest.getOutAccountId(),accountTransferRequest.getOutAccountType(),accountTransferRequest.getOutCustomerType(), InOutFlag.out.getCode(),accountTransferRequest.getTransferAmt(),accountTransferRequest.getTradeType(),accountTransferRequest.getOrderNo());
			if(!BizResponseCode.OK.getCode().equals(outMerAccount.get("code"))){
				return outMerAccount;
			}
		}
		response.put("code", BizResponseCode.OK.getCode());
		response.put("message", BizResponseCode.OK.getMessage());
		return response;
	}

	
	/***
	 * 个人账户操作
	 * */
	public Map<String,Object> personAccountOperate(String platformId,String personalId,String accountType,String customerType,String inOutFlag,String transferAmt,String tradeType,String orderNo){
		Map<String, Object> response = new HashMap<String, Object>();
		PersonalAccount queryPerAccountparam=new PersonalAccount();
		queryPerAccountparam.setPlatformId(platformId);
		queryPerAccountparam.setPersonalId(personalId);
		queryPerAccountparam.setAccountType(accountType);
		try {
			PersonalAccount personalAccount=personalAccountMapper.selectOne(queryPerAccountparam);
			String accountId="";
			if(InOutFlag.out.getCode().equals(inOutFlag)){
				if(null==personalAccount){//商户出账时 个人账户不能为空
					response.put("code", BizResponseCode.PER_ACC_NOTEXIST.getCode());
					response.put("message", BizResponseCode.PER_ACC_NOTEXIST.getMessage());
					log.info("个人或者商户转账接口 返回参数。。。。。。{}", response);
					return response;
				}else if(null!=personalAccount&& AccountState.freeze.equals(personalAccount.getStatus())){
					response.put("code", BizResponseCode.PER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.PER_ACC_FREEZE.getMessage());
					log.info("个人或者商户转账接口。。。。。。{}", response);
					return response;
				}
				if (!MD5.sign(personalAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8").equals(personalAccount.getCheckSum())) {
					response.put("code", BizResponseCode.PER_ACC_BALANCE_NOT_MATE.getCode());
					response.put("message", BizResponseCode.PER_ACC_BALANCE_NOT_MATE.getMessage());
					log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
					return response;
				}
				if(personalAccount.getAccountBalance().compareTo(new BigDecimal(transferAmt))<0){//个人账户余额不足
					response.put("code", BizResponseCode.PER_ACC_BALANCE_NOT_ENOUGH.getCode());
					response.put("message", BizResponseCode.PER_ACC_BALANCE_NOT_ENOUGH.getMessage());
					log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
					return response;
				}
				personalAccount.setAccountBalance(personalAccount.getAccountBalance().subtract(new BigDecimal(transferAmt)));
				personalAccount.setCheckSum(MD5.sign(personalAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8"));
			}
			if(InOutFlag.in.getCode().equals(inOutFlag)){
				if(null==personalAccount){//账户不存在的话则需要开通个人账户
					/**
					 * 获取平台下能开通的账户类型
					 * */
					PlatformAccoutConfig queryaccoutConfig=new PlatformAccoutConfig();
					queryaccoutConfig.setPlatformId(platformId);
					queryaccoutConfig.setCustomerType(customerType);
					queryaccoutConfig.setAccountType(accountType);
					PlatformAccoutConfig accoutConfig =platformAccoutConfigMapper.selectOne(queryaccoutConfig);
					if(null==accoutConfig){//平台支持的账户类型不存在 就没法开户
						response.put("code", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getCode());
						response.put("message", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getMessage());
						log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
						return response;
					}
					/***
					 * 开通个人账户
					 * */
					PersonalAccount newPerAcc= new PersonalAccount();
					newPerAcc.setAccountId(String.valueOf(SnowFlake.getId()));
					newPerAcc.setPlatformId(platformId);
					newPerAcc.setPersonalId(personalId);
					newPerAcc.setAccountType(accountType);
					newPerAcc.setCcy("CNY");
					newPerAcc.setAccountBalance(new BigDecimal(transferAmt));
					newPerAcc.setCheckSum(MD5.sign(transferAmt.toString(), balanceSaltValue, "utf-8"));
					newPerAcc.setFreezeBalance(BigDecimal.ZERO);
					newPerAcc.setStatus(AccountState.normal.getCode());
					newPerAcc.setCreateTime(new Date());
					personalAccountMapper.insertSelective(newPerAcc);
				}else if(null!=personalAccount&& AccountState.freeze.equals(personalAccount.getStatus())){
					response.put("code", BizResponseCode.PER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.PER_ACC_FREEZE.getMessage());
					log.info("个人或者商户转账接口。。。。。。{}", response);
					return response;
				}else{
					if (!MD5.sign(personalAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8").equals(personalAccount.getCheckSum())) {
						response.put("code", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getCode());
						response.put("message", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getMessage());
						log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
						return response;
					}
					personalAccount.setAccountBalance(personalAccount.getAccountBalance().add(new BigDecimal(transferAmt)));
					personalAccount.setCheckSum(MD5.sign(personalAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8"));
				}
				
			}
			personalAccountMapper.updateByPrimaryKeySelective(personalAccount);
			if (StringUtils.isEmpty(accountId)) {
				accountId = personalAccount.getAccountId();
			}
			PersonalAccountJournal personalAccountJournal=new PersonalAccountJournal();
			personalAccountJournal.setJournalId(String.valueOf(SnowFlake.getId()));
			personalAccountJournal.setPlatformId(platformId);
			personalAccountJournal.setPersonalId(personalId);
			personalAccountJournal.setAccountId(accountId);
			personalAccountJournal.setAccountType(accountType);
			personalAccountJournal.setOrderNo(orderNo);
			personalAccountJournal.setInOutFlag(inOutFlag);//来往标志  1：来账   2：往账
			personalAccountJournal.setTradeAmt(new BigDecimal(transferAmt));
			personalAccountJournal.setTradeType(tradeType);//交易类型（支付:01，退款:02，提现:03，充值:04）
			personalAccountJournal.setCreateTime(new Date());
			personalAccountJournalMapper.insertSelective(personalAccountJournal);
			response.put("code", BizResponseCode.OK.getCode());
			response.put("message", BizResponseCode.OK.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			log.info("个人或者商户转账接口-报错。。。。。。{}"+e.getMessage());
			response.put("code", BizResponseCode.SERVICE_NOT_AVALIABLE.getCode());
			response.put("message", BizResponseCode.SERVICE_NOT_AVALIABLE.getMessage());
		}
		return response;
	}
	
	/**
	 * 
	 * 商户账户操作
	 * */
	public Map<String,Object> merchantAccountOperate(String platformId,String merchantId,String accountType,String merchantType,String inOutFlag,String transferAmt,String tradeType,String orderNo){
		Map<String, Object> response = new HashMap<String, Object>();
		MerchantAccount queryMerAccountparam=new MerchantAccount();
		queryMerAccountparam.setPlatformId(platformId);
		queryMerAccountparam.setMerchantId(merchantId);
		queryMerAccountparam.setAccountType(accountType);
		try {
			MerchantAccount merchantAccount = merAccountMapper.selectOne(queryMerAccountparam);
			String accountId="";
			if(InOutFlag.out.getCode().equals(inOutFlag)){
				if(null==merchantAccount){//商户出账时 个人账户不能为空
					response.put("code", BizResponseCode.MER_ACC_NOTEXIST.getCode());
					response.put("message", BizResponseCode.MER_ACC_NOTEXIST.getMessage());
					log.info("个人或者商户转账接口 返回参数。。。。。。{}", response);
					return response;
				}else if(null!=merchantAccount&& AccountState.freeze.equals(merchantAccount.getStatus())){
					response.put("code", BizResponseCode.MER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.MER_ACC_FREEZE.getMessage());
					log.info("个人或者商户转账接口。。。。。。{}", response);
					return response;
				}
				if (!MD5.sign(merchantAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8").equals(merchantAccount.getCheckSum())) {
					response.put("code", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getCode());
					response.put("message", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getMessage());
					log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
					return response;
				}
				if(merchantAccount.getAccountBalance().compareTo(new BigDecimal(transferAmt))<0){//商户账户余额不足
					response.put("code", BizResponseCode.MER_ACC_BALANCE_NOT_ENOUGH.getCode());
					response.put("message", BizResponseCode.MER_ACC_BALANCE_NOT_ENOUGH.getMessage());
					log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
					return response;
				}
				merchantAccount.setAccountBalance(merchantAccount.getAccountBalance().subtract(new BigDecimal(transferAmt)));
				merchantAccount.setCheckSum(MD5.sign(merchantAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8"));
			}
			if(InOutFlag.in.getCode().equals(inOutFlag)){
				if(null==merchantAccount){//账户不存在的话则需要开通商户账户
					/**
					 * 获取平台下能开通的账户类型
					 * */
					PlatformAccoutConfig queryaccoutConfig=new PlatformAccoutConfig();
					queryaccoutConfig.setPlatformId(platformId);
					queryaccoutConfig.setCustomerType(merchantType);
					queryaccoutConfig.setAccountType(accountType);
					PlatformAccoutConfig accoutConfig =platformAccoutConfigMapper.selectOne(queryaccoutConfig);
					if(null==accoutConfig){//平台支持的账户类型不存在 就没法开户
						response.put("code", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getCode());
						response.put("message", BizResponseCode.PLAT_ACC_TYPE_NOT_EXIST.getMessage());
						log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
						return response;
					}
					MerchantAccount newAccount = new MerchantAccount();
					accountId = String.valueOf(SnowFlake.getId());
					newAccount.setAccountId(accountId);
					newAccount.setPlatformId(platformId);
					newAccount.setMerchantId(merchantId);
					newAccount.setMerchantType(merchantType);
					newAccount.setAccountType(accountType);
					newAccount.setCcy("CNY");
					newAccount.setFreezeBalance(BigDecimal.ZERO);
					newAccount.setAccountBalance(new BigDecimal(transferAmt));
					newAccount.setCheckSum(MD5.sign(transferAmt.toString(), balanceSaltValue, "utf-8"));
					newAccount.setStatus(AccountState.normal.getCode());
					newAccount.setCreateTime(new Date());
					merAccountMapper.insertSelective(newAccount);
				}else if(null!=merchantAccount&& AccountState.freeze.equals(merchantAccount.getStatus())){
					response.put("code", BizResponseCode.MER_ACC_FREEZE.getCode());
					response.put("message", BizResponseCode.MER_ACC_FREEZE.getMessage());
					log.info("个人或者商户转账接口。。。。。。{}", response);
					return response;
				}else{
					if (!MD5.sign(merchantAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8").equals(merchantAccount.getCheckSum())) {
						response.put("code", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getCode());
						response.put("message", BizResponseCode.MER_ACC_BALANCE_NOT_MATE.getMessage());
						log.info("个人或者商户转账接口-返回参数。。。。。。{}", response);
						return response;
					}
					merchantAccount.setAccountBalance(merchantAccount.getAccountBalance().add(new BigDecimal(transferAmt)));
					merchantAccount.setCheckSum(MD5.sign(merchantAccount.getAccountBalance().toString(), balanceSaltValue, "utf-8"));
					merAccountMapper.updateByPrimaryKeySelective(merchantAccount);
				}
			}
			if (StringUtils.isEmpty(accountId)) {
				accountId = merchantAccount.getAccountId();
			}
			MerchantAccountJournal merAccountJournal = new MerchantAccountJournal();
			merAccountJournal.setJournalId(String.valueOf(SnowFlake.getId()));
			merAccountJournal.setPlatformId(platformId);
			merAccountJournal.setMerchantId(merchantId);
			merAccountJournal.setFromAccount(accountId);
			merAccountJournal.setAccountType(accountType);
			merAccountJournal.setOrderNo(orderNo);
			merAccountJournal.setInOutFlag(inOutFlag);//来往标志  1：来账   2：往账
			merAccountJournal.setTradeAmt(new BigDecimal(transferAmt));
			merAccountJournal.setTradeType(tradeType);//交易类型（支付:01，退款:02，提现:03，充值:04）
			merAccountJournal.setCreateTime(new Date());
			merchantAccountJournalMapper.insertSelective(merAccountJournal);
			response.put("code", BizResponseCode.OK.getCode());
			response.put("message", BizResponseCode.OK.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			log.info("个人或者商户转账接口-报错。。。。。。{}"+e.getMessage());
			response.put("code", BizResponseCode.SERVICE_NOT_AVALIABLE.getCode());
			response.put("message", BizResponseCode.SERVICE_NOT_AVALIABLE.getMessage());
		}
		return response;
	}

	/**
	 * 解冻并出账
	 * @author centerroot
	 * @time 创建时间:2018年11月2日下午3:44:18
	 * @param unFreezeAndTransferRequest
	 * @return
	 */
	public void unfreezeAndTransfer(UnfreezeAndTransferRequest unFreezeAndTransferRequest) {
		UnfreezeAndOutAccountRequest unFreAndOutAccountRequest = new UnfreezeAndOutAccountRequest();
		IntoAccountRequest intoAccountRequest = new IntoAccountRequest();

		BeanUtils.copyProperties(unFreezeAndTransferRequest, unFreAndOutAccountRequest);
		BeanUtils.copyProperties(unFreezeAndTransferRequest, intoAccountRequest);
		unFreAndOutAccountRequest.setUnfreezeAmt(unFreezeAndTransferRequest.getTradeAmt());
		if (CustomerType.CUST_MERCHANT.getCode().equals(unFreezeAndTransferRequest.getCustomerType())) {
			intoAccountRequest.setCustomerType(CustomerType.CUST_MERCHANT.getCode());
		} else if (CustomerType.CUST_PERSONAL.getCode().equals(unFreezeAndTransferRequest.getCustomerType())){
			intoAccountRequest.setCustomerType(CustomerType.CUST_PERSONAL.getCode());
		} else if (CustomerType.CUST_PLATFORM.getCode().equals(unFreezeAndTransferRequest.getCustomerType())){
			intoAccountRequest.setCustomerType(CustomerType.CUST_PLATFORM.getCode());
		}
		customerOutAccountBiz.unfreezeAndOutAccount(unFreAndOutAccountRequest);
	}

}
